package choice;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import javax.management.relation.RelationNotFoundException;
import java.io.*;
import java.util.*;

public class FileProcess {
    public static void main(String[] args) {
        Map<String, HotelMapping> hotelMappings = getHotelMapping(readLines("C:\\Users\\JasonWu\\Desktop\\choice\\hotel_mapping.txt"));
        List<String> roomTypes = readLines("C:\\Users\\JasonWu\\Desktop\\choice\\rateplan-diff-2014-05-02-1701.ds");
        List<HotelRatePlanAndRoomType> hotelRatePlanAndRoomTypes = createRoomTypes(hotelMappings.keySet(), roomTypes);
        sort(hotelRatePlanAndRoomTypes);
        Map<String, List<HotelTax>> hotelTaxes = createHotelTaxes(hotelMappings.keySet(), readLines("C:\\Users\\JasonWu\\Desktop\\choice\\prop_tax-diff-2014-05-02-1701.ds"));
        for (Map.Entry<String, List<HotelTax>> entry : hotelTaxes.entrySet()) {
            if(entry.getValue().size()>1){
                System.out.println(entry.getKey());
            }
        }
        writeToFiles(hotelMappings, hotelRatePlanAndRoomTypes, hotelTaxes);
    }

    private static Map<String, List<HotelTax>> createHotelTaxes(Set<String> hotelMappings, List<String> taxLines) {
        Map<String, List<HotelTax>> hotelTaxMap = new HashMap<String, List<HotelTax>>();
        for (String taxLine : taxLines) {
            String[] fields = StringUtils.split(taxLine, "|");
            String hotelCode = StringUtils.trim(fields[1]);
            if (StringUtils.isBlank(hotelCode)) {
                System.out.println(taxLine);
                continue;
            }
            if (!hotelMappings.contains(hotelCode)) {
                //System.out.println(String.format("unmapped hotel:%s", hotelCode));
                continue;
            }
            if (StringUtils.equalsIgnoreCase(fields[0], "Delete")) {
                continue;
            }
            HotelTax hotelTax = new HotelTax();
            hotelTax.setHotelCode(hotelCode);
            hotelTax.setStart(fields[2]);
            hotelTax.setEnd(fields[3]);
            hotelTax.setTaxOneType(fields[4]);
            hotelTax.setTaxOneAmount(fields[5]);
            hotelTax.setTaxTwoType(fields[6]);
            hotelTax.setTaxTwoAmount(fields[7]);
            List<HotelTax> hotelTaxes = hotelTaxMap.get(hotelCode);
            if (hotelTaxes == null) {
                hotelTaxes = new ArrayList<HotelTax>();
                hotelTaxMap.put(hotelCode, hotelTaxes);
            }
            hotelTaxes.add(hotelTax);
        }
        return hotelTaxMap;
    }

    private static Map<String, HotelMapping> getHotelMapping(List<String> lines) {
        HashMap<String, HotelMapping> hotelMappings = new HashMap<String, HotelMapping>();
        for (String hotelLine : lines) {
            String[] fields = StringUtils.split(hotelLine, ",");
            String hotelCode = StringUtils.trim(fields[1]);
            if (StringUtils.isBlank(hotelCode)) {
                System.out.println(hotelLine);
                continue;
            }
            HotelMapping hotelMapping = new HotelMapping();
            hotelMapping.setBrand(StringUtils.trim(fields[0]));
            hotelMapping.setHotelCode(hotelCode);
            hotelMapping.setHotelName(StringUtils.trim(fields[2]));
            hotelMapping.setCity(StringUtils.trim(fields[3]));
            hotelMapping.setState(StringUtils.trim(fields[4]));
            hotelMapping.setCountry(StringUtils.trim(fields[5]));
            hotelMappings.put(hotelCode, hotelMapping);
        }
        return hotelMappings;
    }

    private static void sort(List<HotelRatePlanAndRoomType> hotelRatePlanAndRoomTypes) {
        Collections.sort(hotelRatePlanAndRoomTypes, new Comparator<HotelRatePlanAndRoomType>() {
            @Override
            public int compare(HotelRatePlanAndRoomType o1, HotelRatePlanAndRoomType o2) {
                return o1.getHotelCode().compareTo(o2.getHotelCode());
            }
        });
    }

    private static void writeToFiles(Map<String, HotelMapping> hotelMappings, List<HotelRatePlanAndRoomType> hotelRatePlanAndRoomTypes, Map<String, List<HotelTax>> hotelTaxesMap) {
        try {
            FileWriter fileWriter = new FileWriter(new File("C:\\Users\\JasonWu\\Desktop\\choice\\room_types.txt"));
            for (HotelRatePlanAndRoomType hotelRatePlanAndRoomType : hotelRatePlanAndRoomTypes) {
                List<HotelTax> hotelTaxes = hotelTaxesMap.get(hotelRatePlanAndRoomType.getHotelCode());
                if (CollectionUtils.isEmpty(hotelTaxes)) {
                    fileWriter.write(hotelMappings.get(hotelRatePlanAndRoomType.getHotelCode()).toString());
                    fileWriter.write(",");
                    fileWriter.write(hotelRatePlanAndRoomType.toString());
                    fileWriter.write(",");
                    fileWriter.write("\r\n");
                    continue;
                }
                if (hotelTaxes.size() > 1) {
                    for (HotelTax hotelTax : hotelTaxes) {
                        fileWriter.write(hotelMappings.get(hotelRatePlanAndRoomType.getHotelCode()).toString());
                        fileWriter.write(",");
                        fileWriter.write(hotelRatePlanAndRoomType.toString());
                        fileWriter.write(",");
                        fileWriter.write(hotelTax.toString());
                        fileWriter.write("\r\n");
                    }
                    continue;
                }
                fileWriter.write(hotelMappings.get(hotelRatePlanAndRoomType.getHotelCode()).toString());
                fileWriter.write(",");
                fileWriter.write(hotelRatePlanAndRoomType.toString());
                fileWriter.write(",");
                fileWriter.write(hotelTaxes.get(0).toString());
                fileWriter.write("\r\n");
            }
            fileWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static List<HotelRatePlanAndRoomType> createRoomTypes(Set<String> hotelMappings, List<String> roomTypes) {
        Map<String, HotelRatePlanAndRoomType> hotelRatePlanAndRoomTypes = new TreeMap<String, HotelRatePlanAndRoomType>();
        for (String roomTypeLine : roomTypes) {
            String[] fields = StringUtils.split(roomTypeLine, "|");
            String hotelCode = getValueByParseField(fields, RtPlanAndRmTypeParseField.HOTEL_CODE);
            if (StringUtils.isBlank(hotelCode)) {
                System.out.println(roomTypeLine);
                continue;
            }
            if (!hotelMappings.contains(hotelCode)) {
                //System.out.println(String.format("unmapped hotel:%s", hotelCode));
                continue;
            }
            if (StringUtils.equalsIgnoreCase(fields[0], "Delete")) {
                continue;
            }
            String roomTypeCode = getValueByParseField(fields, RtPlanAndRmTypeParseField.ROOM_TYPE_CODE);

            HotelRatePlanAndRoomType hotelRatePlanAndRoomType = new HotelRatePlanAndRoomType();
            hotelRatePlanAndRoomType.setHotelCode(hotelCode);
            hotelRatePlanAndRoomType.setRoomTypeCode(roomTypeCode);
            hotelRatePlanAndRoomType.setDescription(replaceComma(getValueByParseField(fields, RtPlanAndRmTypeParseField.DESCRIPTION)));
            hotelRatePlanAndRoomType.setRoomTypeFeatures(replaceComma(getValueByParseField(fields, RtPlanAndRmTypeParseField.ROOM_TYPE_FEATURES)));
            hotelRatePlanAndRoomType.setNumBeds(getValueByParseField(fields, RtPlanAndRmTypeParseField.NUM_BEDS));
            hotelRatePlanAndRoomType.setMaxOcc(getValueByParseField(fields, RtPlanAndRmTypeParseField.MAX_OCC));
            hotelRatePlanAndRoomType.setTaxInclude(getValueByParseField(fields, RtPlanAndRmTypeParseField.TAX_INCL));
            String key = String.format("%s:%s", hotelCode, roomTypeCode);
            hotelRatePlanAndRoomTypes.put(key, hotelRatePlanAndRoomType);
        }
        return new ArrayList<HotelRatePlanAndRoomType>(hotelRatePlanAndRoomTypes.values());
    }

    private static String replaceComma(String value) {
        if (StringUtils.contains(value, ",")) {
            return StringUtils.replace(value, ",", " ");
        }
        return value;
    }

    private static String getValueByParseField(String[] splits, RtPlanAndRmTypeParseField rtPlanAndRmTypeParseField) {
        return rtPlanAndRmTypeParseField.getIndex() >= splits.length ? null : splits[rtPlanAndRmTypeParseField.getIndex()].trim();
    }

    private static List<String> readLines(String filePath) {
        List<String> lines = new ArrayList<String>();
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePath))));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                lines.add(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return lines;
    }
}
